﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;

namespace BiaoYinTest
{
    public class BiaoYinControl : Control
    {
        Canvas pageCanvas;
        Polygon item;
        ItemsControl Items;
        RectangleGeometry rectangleGeometry;
        ScrollViewer scrollContainer;

        private static readonly new DependencyProperty DataContextProperty = DependencyProperty.Register("DataContext", typeof(object), typeof(BiaoYinControl), new PropertyMetadata(new PropertyChangedCallback(OnDataContextPropertyChanged)));


        static void OnDataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PageInfo pInfo = e.NewValue as PageInfo;
            double width = (double)d.GetValue(WidthProperty);
            double height = (double)d.GetValue(HeightProperty);

            pInfo.Resize(width, height);
        }


        Polygon selectedItem;


        public BiaoYinControl()
        {
            this.DefaultStyleKey = typeof(BiaoYinControl);

            base.SetBinding(DataContextProperty, new Binding());
        }

        public override void OnApplyTemplate()
        {
            pageCanvas = base.GetTemplateChild("PageCanvas") as Canvas;
            item = base.GetTemplateChild("Item") as Polygon;
            rectangleGeometry = base.GetTemplateChild("rectangleGeometry") as RectangleGeometry;
            scrollContainer = base.GetTemplateChild("scrollContainer") as ScrollViewer;
            selectedItem = base.GetTemplateChild("SelectedItem") as Polygon;
            Items = base.GetTemplateChild("Items") as ItemsControl;

            base.OnApplyTemplate();

            pageCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(pageCanvas_MouseLeftButtonDown);
            pageCanvas.MouseLeftButtonUp += new MouseButtonEventHandler(pageCanvas_MouseLeftButtonUp);
            pageCanvas.MouseWheel += new MouseWheelEventHandler(pageCanvas_MouseWheel);
            pageCanvas.MouseMove += new MouseEventHandler(pageCanvas_MouseMove);
        }

        Binding createTwoWayBinding(string path)
        {
            Binding bd = new Binding(path);
            bd.Mode = BindingMode.TwoWay;
            return bd;
        }

        int snakeWidth = 5;

        void pageCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (isInHotEdit)
            {
                if (editStart)
                {
                    Point lastPoint = e.GetPosition(pageCanvas);

                    if (Math.Abs(lastLine.X1 - lastPoint.X) > Math.Abs(lastLine.Y1 - lastPoint.Y))
                    {
                        //延X轴方向移动
                        lastPoint.Y = lastLine.Y1;

                        foreach (Point pt in ptCollection)
                        {
                            if (lastPoint.X > pt.X - snakeWidth && lastPoint.X < pt.X + snakeWidth)
                            {
                                lastPoint.X = pt.X;
                                break;
                            }
                        }
                    }
                    else
                    {
                        lastPoint.X = lastLine.X1;

                        foreach (Point pt in ptCollection)
                        {
                            if (lastPoint.Y > pt.Y - snakeWidth && lastPoint.Y < pt.Y + snakeWidth)
                            {
                                lastPoint.Y = pt.Y;
                                break;
                            }
                        }
                    }

                    lastLine.X2 = lastPoint.X;
                    lastLine.Y2 = lastPoint.Y;

                }
            }
            else if (pageCanvasMouseDown)
            {
                pageCanvasMouseMoved = true;

                Point currentPoint = e.GetPosition(null);

                double xOffset = currentPoint.X - downPoint.X;
                double yOffset = currentPoint.Y - downPoint.Y;

                double heightRate = scrollContainer.ExtentHeight / scrollContainer.Height;
                double widthRate = scrollContainer.ExtentWidth / scrollContainer.Width;

                scrollContainer.ScrollToVerticalOffset(scrollContainer.VerticalOffset - yOffset * heightRate);
                scrollContainer.ScrollToHorizontalOffset(scrollContainer.HorizontalOffset - xOffset * widthRate);
                downPoint = currentPoint;
            }
        }

        bool pageCanvasMouseDown = false;
        bool pageCanvasMouseMoved = false;
        Point downPoint;
        bool editStart = false;

        void pageCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            pageCanvasMouseDown = true;

            downPoint = e.GetPosition(null);
            pageCanvas.CaptureMouse();
        }

        void pageCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            PageInfo pInfo = this.DataContext as PageInfo;

            Point clickPoint = e.GetPosition(sender as UIElement);
            double currentVerticalOffset = scrollContainer.VerticalOffset;
            double currentHorizontalOffset = scrollContainer.HorizontalOffset;
            double w = pInfo.Width;
            double h = pInfo.Height;

            double v = 0.01 * (e.Delta / Math.Abs(e.Delta));
            double rateOld = pInfo.Rate;
            double rateNew = pInfo.Rate + v;

            rateNew = pInfo.SetRate(rateNew);

            double xOffset = clickPoint.X * rateNew - clickPoint.X * rateOld;
            double yOffset = clickPoint.Y * rateNew - clickPoint.Y * rateOld;

            double heightRate = scrollContainer.ExtentHeight / scrollContainer.Height;
            double widthRate = scrollContainer.ExtentWidth / scrollContainer.Width;


            scrollContainer.ScrollToHorizontalOffset(scrollContainer.HorizontalOffset + xOffset * widthRate);
            scrollContainer.ScrollToVerticalOffset(scrollContainer.VerticalOffset + yOffset * heightRate);
        }

        PointCollection ptCollection = new PointCollection();
        Line lastLine;
        Canvas editCanvas;

        void pageCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            pageCanvasMouseDown = false;

            pageCanvas.ReleaseMouseCapture();

            if (isInHotEdit)
            {
                editStart = true;

                Point lastPoint = e.GetPosition(pageCanvas);



                if (ptCollection.Count > 0)
                {
                    if (Math.Abs(lastLine.X1 - lastPoint.X) > Math.Abs(lastLine.Y1 - lastPoint.Y))
                    {
                        //延X轴方向移动
                        lastPoint.Y = lastLine.Y1;

                        foreach (Point pt in ptCollection)
                        {
                            if (lastPoint.X > pt.X - snakeWidth && lastPoint.X < pt.X + snakeWidth)
                            {
                                lastPoint.X = pt.X;
                                break;
                            }
                        }
                    }
                    else
                    {
                        lastPoint.X = lastLine.X1;

                        foreach (Point pt in ptCollection)
                        {
                            if (lastPoint.Y > pt.Y - snakeWidth && lastPoint.Y < pt.Y + snakeWidth)
                            {
                                lastPoint.Y = pt.Y;
                                break;
                            }
                        }
                    }

                    ptCollection.Add(lastPoint);

                    Point first = ptCollection.First();
                    Rect rect = new Rect(first.X - snakeWidth, first.Y - snakeWidth, snakeWidth * 2, snakeWidth * 2);
                    if (rect.Contains(lastPoint))
                    {
                        editStart = false;
                        pageCanvas.Children.Remove(editCanvas);
                        editCanvas = null;

                        (this.DataContext as PageInfo).SelectedItem.UpdatePoints(ptCollection);

                        ptCollection.Clear();
                        return;
                    }
                }
                else
                {
                    editCanvas = new Canvas();
                    pageCanvas.Children.Add(editCanvas);
                    ptCollection.Add(lastPoint);

                }
                lastLine = new Line();
                lastLine.Stroke = new SolidColorBrush(Colors.Black);
                editCanvas.Children.Add(lastLine);
                lastLine.X1 = lastLine.X2 = lastPoint.X;
                lastLine.Y1 = lastLine.Y2 = lastPoint.Y;

            }
            else
            {
                //MouseClick
                if (!pageCanvasMouseMoved)
                {
                    if (e.OriginalSource is Polygon)
                    {
                        if (e.OriginalSource is Polygon)
                        {
                            SelectItem(e.OriginalSource);
                        }
                        else
                        {
                            ClearSelectedItem();
                        }

                        //raiseSelectedItemChanged();
                    }
                }
            }

            pageCanvasMouseMoved = false;
        }

        public void SelectItem(object originalSource)
        {
            PageInfo pInfo = this.DataContext as PageInfo;
            Polygon p = originalSource as Polygon;
            IBlock m = p.DataContext as IBlock;

            if (m.IsSelected)
            {
                m.IsSelected = false;

                pInfo.SelectedItems.Remove(m);
            }
            else
            {
                m.IsSelected = true;
                pInfo.SelectedItems.Add(m);
            }

        }

        private void ClearSelectedItem()
        {
            PageInfo pInfo = this.DataContext as PageInfo;

            pInfo.SelectedItems.Clear();
        }

        public void EditHotArea(bool status)
        {
            if (status)
            {
                selectedItem.Visibility = Visibility.Visible;
                Items.Visibility = Visibility.Collapsed;

                PageInfo pInfo = this.DataContext as PageInfo;

                selectedItem.DataContext = pInfo.SelectedItem;

                isInHotEdit = true;
            }
            else
            {
                selectedItem.Visibility = Visibility.Collapsed;
                Items.Visibility = Visibility.Visible;

                PageInfo pInfo = this.DataContext as PageInfo;

                selectedItem.DataContext = pInfo.SelectedItem;

                isInHotEdit = false;
            }
        }

        bool isInHotEdit = false;

        public bool IsInHotEdit
        {
            get { return isInHotEdit; }
        }

        internal void UpdateSize(double width, double height)
        {
            this.Width = width;
            this.Height = height;
            rectangleGeometry.Rect = new Rect(new Point(0, 0), new Size(width, height));

            PageInfo pInfo = this.DataContext as PageInfo;

            if (pInfo != null)
            {
                pInfo.Resize(width, height);
            }
        }
    }

}
